/******************************************************************************
 copyright (C), 2018, hisilicon tech. co., ltd.
******************************************************************************
file name     : mpi_pm.c
version       : initial draft
author        : hisilicon multimedia software group
created       : 2018/09/17
last modified :
description   :
function list :
******************************************************************************/
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/poll.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <sys/mman.h>
#include <semaphore.h>
#include <stdlib.h>
#include "hi_type.h"
#include "hi_common.h"
#include "hi_debug.h"

#include "hi_comm_video.h"
#include "hi_comm_pm.h"
#include "mkp_pm.h"
#include "mpi_pm.h"
#include "mpi_sys.h"


#ifdef __cplusplus
#if __cplusplus
extern "C"
{
#endif
#endif

static hi_s32 g_pm_mpi_fd = -1;              /* device handle */
static const char *g_psz_dev_name = "/dev/pm";



static pthread_mutex_t s_pm_mutex = PTHREAD_MUTEX_INITIALIZER;

#define PM_MUTEX_LOCK() \
    do { \
        (void)pthread_mutex_lock(&s_pm_mutex); \
    }while(0)

#define PM_MUTEX_UNLOCK() \
    do { \
        (void)pthread_mutex_unlock(&s_pm_mutex); \
    }while(0)

#define CHECK_PM_OPEN()\
    do{\
        hi_s32 ret;\
        ret = mpi_pm_check_open();\
        if(HI_SUCCESS != ret)\
        {\
            return ret;\
        }\
    } while (0)


#define MPI_CHECK_NULL_PTR(ptr)\
    do{\
        hi_s32 ret;\
        ret = mpi_pm_check_null_ptr((hi_void*)ptr);\
        if(HI_SUCCESS != ret)\
        {\
            return ret;\
        }\
    }while(0)

static hi_s32 mpi_pm_check_open(hi_void)
{
    PM_MUTEX_LOCK();
    if (g_pm_mpi_fd == -1) {
        g_pm_mpi_fd = open(g_psz_dev_name, O_RDWR, 0);
        if (g_pm_mpi_fd == -1) {
            PM_MUTEX_UNLOCK();
            printf("func %s open '%s' failed! \n", __FUNCTION__, g_psz_dev_name);
            return HI_ERR_PM_SYS_NOTREADY;
        }
    }
    PM_MUTEX_UNLOCK();
    return HI_SUCCESS;
}

static hi_s32 mpi_pm_check_null_ptr(hi_void *ptr)
{
    if (ptr == NULL) {
        printf("func %s NULL pointer detected\n", __FUNCTION__);
        return HI_ERR_PM_NULL_PTR;
    }
    return HI_SUCCESS;
}

/*****************************************************************************
 prototype    : hi_mpi_pm_set_single_media_param
 description  : set media obj frequency
 input        : PM_HANDLE  h_handle
 output       : none
 return value :
 calls        :
 called by    :
</$>
  history        :
  1.date         : 2018/09/17
    author       :
    modification : created function
<$/>
*****************************************************************************/
hi_s32 hi_mpi_pm_set_media_param(hi_mpi_pm_media_cfg *pm_param)
{
    CHECK_PM_OPEN();
    MPI_CHECK_NULL_PTR(pm_param);
    return ioctl(g_pm_mpi_fd, PM_SET_MEDIA_PARAM, pm_param);
}

/*****************************************************************************
 prototype    : hi_mpi_pm_get_media_param
 description  : add a task to a pm job
 input        : PM_HANDLE  h_handle
 output       : none
 return value :
 calls        :
 called by    :
</$>
  history        :
  1.date         : 2018/09/17
    author       :
    modification : created function
<$/>
*****************************************************************************/
hi_s32 hi_mpi_pm_get_media_param(hi_mpi_pm_media_cfg *pm_param)
{
    CHECK_PM_OPEN();
    MPI_CHECK_NULL_PTR(pm_param);
    return ioctl(g_pm_mpi_fd, PM_GET_MEDIA_PARAM, pm_param);
}

/*****************************************************************************
 prototype    : hi_mpi_pm_set_single_media_param
 description  : add a task to a pm job
 input        : PM_HANDLE  h_handle
 output       : none
 return value :
 calls        :
 called by    :
</$>
  history        :
  1.date         : 2018/09/17
    author       :
    modification : created function
<$/>
*****************************************************************************/
hi_s32 hi_mpi_pm_set_single_media_param(hi_mpi_pm_sigle_media_cfg *pmsinle_param)
{
    CHECK_PM_OPEN();
    MPI_CHECK_NULL_PTR(pmsinle_param);
    return ioctl(g_pm_mpi_fd, PM_SET_SINGLE_MEDIA_PARAM, pmsinle_param);
}

/*****************************************************************************
 prototype    : hi_mpi_pm_get_temperature
 description  : get temperature form PM
 input        : none
 output       : temperature
 return value :
 calls        :
 called by    :
</$>
  history        :
  1.date         : 2018/09/17
    author       :
    modification : created function
<$/>
*****************************************************************************/

hi_s32 hi_mpi_pm_get_temperature(hi_s32 *pm_tempe)
{
    CHECK_PM_OPEN();
    MPI_CHECK_NULL_PTR(pm_tempe);
    return ioctl(g_pm_mpi_fd, PM_GET_TEMPERATURE, pm_tempe);
}
/*****************************************************************************
 prototype    : hi_mpi_pm_set_single_media_param
 description  : set media obj frequency
 input        : PM_HANDLE  h_handle
 output       : none
 return value :
 calls        :
 called by    :
</$>
  history        :
  1.date         : 2018/09/17
    author       :
    modification : created function
<$/>
*****************************************************************************/
hi_s32 hi_mpi_pm_enable_svp_accelerator(hi_bool enable)
{
    CHECK_PM_OPEN();
    int int_enable = (int)enable;
    return ioctl(g_pm_mpi_fd, PM_SVP_ENABLE_CTRL, int_enable);
}

#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* __cplusplus */
